package cn.org.xwb.bookmall.user.controller;

import cn.hutool.core.convert.Convert;
import cn.org.xwb.bookmall.model.constant.AccountConst;
import cn.org.xwb.bookmall.model.po.Car;
import cn.org.xwb.bookmall.model.service.impl.CarServiceImpl;
import cn.org.xwb.bookmall.model.vo.CarVo;
import cn.org.xwb.bookmall.user.annotation.IsLoginParam;
import cn.org.xwb.common.encrypt.annotation.des.DesEn;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDe;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDeParam;
import cn.org.xwb.common.encrypt.constant.EncryptConstant;
import cn.org.xwb.common.error.annotation.ServerErrorCatch;
import cn.org.xwb.common.model.vo.RespResult;
import cn.org.xwb.common.valid.annotation.nu.NotNull;
import cn.org.xwb.common.valid.annotation.nu.NotNullParam;
import cn.org.xwb.common.valid.annotation.str.StrNotNull;
import cn.org.xwb.common.valid.annotation.str.StrNotNullParam;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping("/car")
public class UserCarController {

    @Autowired
    private CarServiceImpl carService;

    @GetMapping("/list")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    @DesEn
    public RespResult<Object> getCarList(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String desKey,
            @RequestParam("id") @NotNullParam
            Long id
    ) {
        List<CarVo> carVos = carService.findAllFromCache(id);
        if (Objects.isNull(carVos)) return RespResult.fail("获取购物车列表失败");
        Collections.reverse(carVos);
        return RespResult.success("获取购物车列表成功", carVos);
    }

    @PostMapping("/add")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    @Transactional
    public RespResult<Object> addCar(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam("userId") @NotNullParam
            Long userId,
            @RequestParam("productId") @NotNullParam
            Long productId,
            @RequestParam("productOptionId") @NotNullParam
            Long productOptionId,
            @RequestParam("num") @NotNullParam
            Integer num
    ) {
        List<CarVo> carVos = carService.findAllFromCache(userId);
        Car car = null;
        for (CarVo carVo : carVos) {
            if (carVo.getProductId() == productId && carVo.getProductOptionId() == productOptionId) {
                carVo.setNum(carVo.getNum() + num);
                car = Convert.convert(Car.class, carVo);
                break;
            }
        }
        if (Objects.isNull(car)) {
            car = new Car(null, userId, productId, productOptionId, num);
            int res = carService.getBaseMapper().insert(car);
            if (res < 1) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RespResult.fail("添加购物车失败");
            }
        }
        Boolean res1 = updateCar(carVos);
        if (!res1) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("添加购物车失败");
        }
        carVos = carService.findAndCacheAll(userId);
        if (Objects.isNull(carVos)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("添加购物车失败");
        }
        return RespResult.success("添加购物车成功");
    }

    private Boolean updateCar(List<CarVo> carVos) {
        for (CarVo carVo : carVos) {
            Car car = Convert.convert(Car.class, carVo);
            boolean res = carService.updateById(car);
            if (!res) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        }
        return true;
    }

    @PostMapping("/update")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    @Transactional
    public RespResult<Object> updateCarProduct(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam("userId") @NotNullParam
            Long userId,
            @RequestParam("id") @NotNullParam
            Long id,
            @RequestParam(value = "productOptionId", required = false)
            Long productOptionId,
            @RequestParam(value = "productId", required = false)
            Long productId,
            @RequestParam(value = "num", required = false)
            Integer num
    ) {
        Car car = new Car();
        car.setNum(num);
        car.setId(id);
        car.setUserId(userId);
        car.setProductId(productId);
        car.setProductOptionId(productOptionId);
        LambdaQueryWrapper<Car> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(Car::getProductId, productId)
                .and(i -> i.eq(Car::getProductOptionId, productOptionId))
                .and(i -> i.eq(Car::getUserId, userId));
        Car car1 = carService.getOne(queryWrapper);
        boolean res = false;
        if (Objects.isNull(car1)) res = carService.updateById(car);
        else {
            car1.setNum(car1.getNum() + num);
            res = carService.updateById(car1);
            if (!res) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RespResult.fail("购物车商品信息修改失败");
            }
            res = carService.removeById(id);
        }
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("购物车商品信息修改失败");
        }
        List<CarVo> carVos = carService.findAndCacheAll(userId);
        if (Objects.isNull(carVos)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("购物车商品信息修改失败");
        }
        return RespResult.success("购物车商品信息修改成功");
    }

    @PostMapping("/del")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    @Transactional
    public RespResult<Object> delCarProduct(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam("userId") @NotNullParam
            Long userId,
            @RequestParam("id") @NotNullParam
            Long id
    ) {
        boolean res = carService.removeById(id);
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("购物车商品删除失败");
        }
        List<CarVo> carVos = carService.findAndCacheAll(userId);
        if (Objects.isNull(carVos)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("购物车商品删除失败");
        }
        return RespResult.success("购物车商品删除成功");
    }

    public RespResult<Object> delCarProduct(Long userId, Long id) {
        boolean res = carService.removeById(id);
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("购物车商品删除失败");
        }
        List<CarVo> carVos = carService.findAndCacheAll(userId);
        if (Objects.isNull(carVos)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("购物车商品删除失败");
        }
        return RespResult.success("购物车商品删除成功");
    }

}
